// https://blog.csdn.net/rxbook/article/details/130646031

package main

import "fmt"

type Users struct {
	Name  string
	Age   int
	hobby []string
}

func (user *Users) SetUserName(name string) {
	user.Name = name
}

// SetUserName()的等价函数
func SetName(user *Users, name string) {
	user.Name = name
}

func (user Users) GetUserName() {
	fmt.Printf("用户名是:%v \n", user.Name)
}

// GetUserName()的等价函数
func GetName(user *Users) {
	fmt.Printf("用户名是:%v \n", user.Name)
}

/* 基于自定义的type类型创建方法 */
type Age uint
type Name string

// 不同的接收者可以使用相同的方法名
func (age Age) Show() {
	fmt.Println("年龄是", age)
}
func (name Name) Show() {
	fmt.Println("姓名是", name)
}

func main() {
	/* 方法实例化 */
	// 通过类型 Users 的变量实例调用方法
	var user1 Users
	user1.SetUserName("张三")
	user1.GetUserName() //用户名是:张三

	// 通过类型 *Users 的变量实例调用方法
	user2 := &Users{}
	user2.SetUserName("李四")
	user2.GetUserName() //用户名是:李四

	// 直接通过 Users 结构体调用方法并传入实例
	var user3 Users
	(*Users).SetUserName(&user3, "王五")
	Users.GetUserName(user3) //用户名是:王五

	/* 可以将方法作为右值赋值给一个函数类型的变量 */
	var user4 Users
	f1 := (*Users).SetUserName
	f2 := Users.GetUserName
	fmt.Printf("f1的类型是: %T \n", f1) //f1的类型是: func(*main.Users, string)
	fmt.Printf("f2的类型是: %T \n", f2) //f2的类型是: func(main.Users)
	f1(&user4, "赵六")
	f2(user4) //用户名是:赵六
	println()

	/* 基于自定义的type类型创建的方法实例化 */
	age := Age(20)
	age.Show() //年龄是 20
	name := Name("zhangsan")
	name.Show() //姓名是 zhangsan
}
